home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / dev / misc / LEDA_gene.lha / LEDA-3.1c-generic / prog / graphics / map.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-05  |  10.7 KB  |  489 lines

  1. #include <LEDA/basic.h>
  2. #include <LEDA/slist.h>
  3. #include <LEDA/plane.h>
  4. #include <LEDA/window.h>
  5.  
  6. #include<math.h>
  7.  
  8. const int WORDS = 6;    // maximal size of placement vectors (in words)
  9.  
  10. const int N     = 96;   // maximal number of input points = 16 * WORDS
  11.  
  12. typedef unsigned long word;
  13.  
  14. class PLACEMENT
  15. {
  16.   word A[WORDS];
  17.  
  18.   word cache;      // cache of 16 last written entries
  19.  
  20.   public:
  21.  
  22.   PLACEMENT();
  23.  
  24.   word get_last_word() const { return cache;}
  25.  
  26.   word get_last_word(int i) const 
  27.   { return (i>0) ? (cache << ((16-i)<<1)) : 0; }
  28.   
  29.   int read(int i) const 
  30.   { return (A[i>>4] >> ((i&15)<<1)) & 3; }
  31.  
  32.   void write(int i, int pos) 
  33.   { A[i>>4] |= (pos << ((i&15)<<1));
  34.     cache <<=2;
  35.     cache |= pos;
  36.    } 
  37.  
  38.   LEDA_MEMORY(PLACEMENT)
  39.  
  40. };
  41.  
  42.  
  43. PLACEMENT::PLACEMENT()
  44. { for(int i = 0; i < WORDS; i++) A[i] = 0; }
  45.  
  46.  
  47. typedef PLACEMENT* placement;
  48.  
  49.  
  50. static window W(600,650);
  51.  
  52. static color node_color1 = blue;
  53. static color node_color2 = red;
  54. static color node_color3 = green;
  55. static color rect_color  = yellow;
  56.  
  57. void draw_rec(window& W, double x1, double y1, double x2, double y2)
  58. { if (!W.mono())
  59.       W.draw_filled_rectangle(x1,y1,x2,y2,rect_color);
  60.   W.draw_rectangle(x1,y1,x2,y2);
  61.  }
  62.  
  63.  
  64. void draw_config(window& W, const list<point>& L, PLACEMENT& P, double sig, 
  65.                                                                 int maxp = -1)
  66. {
  67.         /*--------*--------*
  68.          |        |        |
  69.          |   0    |    1   |
  70.          |        |        |
  71.          *--------p--------*
  72.          |        |        |
  73.          |   2    |    3   |
  74.          |        |        |
  75.          *--------*--------*/
  76.  
  77.   int   i=0;
  78.   point p;
  79.  
  80.   if (maxp <0) maxp = L.length();
  81.  
  82.   W.clear();
  83.  
  84.   forall(p,L)
  85.   {
  86.     double x = p.xcoord();
  87.     double y = p.ycoord();
  88.  
  89.     int  pos = P.read(i++);
  90.  
  91.     switch(pos)
  92.     { case 0 : draw_rec(W,x,y,x-sig,y+sig);
  93.                break;
  94.  
  95.       case 1 : draw_rec(W,x,y,x+sig,y+sig);
  96.                break;
  97.       
  98.       case 2 : draw_rec(W,x,y,x-sig,y-sig);
  99.                break; 
  100.       
  101.       case 3 : draw_rec(W,x,y,x+sig,y-sig);
  102.                break;
  103.     }
  104.  
  105.     if (i > maxp) break;
  106.   }
  107.  
  108.   forall(p,L) W.draw_filled_node(p,node_color1);
  109.  
  110. }
  111.  
  112.  
  113.  
  114.  
  115. int** D[N][4];   // D[N][4][N][4]
  116.                  //  
  117.                  // D[p][i][q][j] gives maximal possible sigma for square at 
  118.                  // point p in position i and square at point q in position j
  119.  
  120.  
  121. void initialize_matrix(const list<point>& p_list)
  122. {
  123.   list_item it1, it2;
  124.  
  125.   int n = p_list.length();
  126.  
  127.   int i,j,p1,p2;
  128.  
  129.   for(i=0;i < n; i++)
  130.      for(p1=0;p1 < 4; p1++)
  131.      { int** ptr = new int*[n];
  132.        D[i][p1] = ptr;
  133.        for(j=0; j<n; j++) ptr[j] = new int[4];
  134.        }
  135.  
  136.  
  137.   i = 0;
  138.   forall_items(it1,p_list)
  139.   { 
  140.     point p = p_list[it1];
  141.  
  142.     j = 0;
  143.     forall_items(it2,p_list)
  144.      { 
  145.        if (it1==it2) break;
  146.  
  147.        point q = p_list[it2];
  148.  
  149.  
  150.        int xrel  = int(p.xcoord() - q.xcoord());
  151.        int yrel  = int(p.ycoord() - q.ycoord());
  152.        int xdist = int(fabs(xrel));
  153.        int ydist = int(fabs(yrel));
  154.        int max_xy = Max(xdist,ydist);
  155.  
  156.        int d_00  = max_xy;
  157.        int d_01  = (xrel>0) ? Max(xdist/2,ydist) : MAXINT;
  158.        int d_01r = (xrel<0) ? Max(xdist/2,ydist) : MAXINT;
  159.        int d_02  = (yrel<0) ? Max(xdist,ydist/2) : MAXINT;
  160.        int d_02r = (yrel>0) ? Max(xdist,ydist/2) : MAXINT;
  161.        int d_03  = (xrel>0 && yrel<0) ? max_xy/2 : MAXINT;
  162.        int d_03r = (xrel<0 && yrel>0) ? max_xy/2 : MAXINT;
  163.        int d_12  = (xrel<0 && yrel<0) ? max_xy/2 : MAXINT;
  164.        int d_12r = (xrel>0 && yrel>0) ? max_xy/2 : MAXINT;
  165.  
  166.  
  167.        for(p1=0; p1<4;p1++)
  168.          for(p2=0; p2<4;p2++)
  169.           switch(p1 - p2)
  170.           {
  171.             case  0 : D[i][p1][j][p2] = d_00;
  172.                       break;
  173.      
  174.             case -1 : D[i][p1][j][p2] = (p1==1) ? d_12 : d_01;
  175.                       break;
  176.      
  177.             case  1 : D[i][p1][j][p2] = (p1==2) ? d_12r : d_01r;
  178.                       break;
  179.      
  180.             case -2 : D[i][p1][j][p2] = d_02;
  181.                       break;
  182.      
  183.             case  2 : D[i][p1][j][p2] = d_02r;
  184.                       break;
  185.      
  186.             case -3 : D[i][p1][j][p2] = d_03;
  187.                       break;
  188.      
  189.             case  3 : D[i][p1][j][p2] = d_03r;
  190.                       break;
  191.           }
  192.     
  193.       j++;
  194.      }
  195.  
  196.     i++;
  197.  
  198.    }
  199.  
  200. }
  201.  
  202.  
  203.  
  204.  
  205. bool find_placement(list<point>& L, int sigma, PLACEMENT& P)
  206.   // determines whether a placement is possible and returns it in P 
  207.   // P is unchanged if there is no placment possible 
  208.   
  209.   slist<placement> T,Tnew;
  210.  
  211.   int n = L.length();
  212.  
  213.   placement v;
  214.  
  215.   register int   p,q,k,i;
  216.   register word  buf,plw;
  217.   register int** dist_to_p;
  218.  
  219.   point a;
  220.  
  221.   float X[N];
  222.   float Y[N];
  223.  
  224.   p = 0;
  225.  
  226.   forall(a,L) 
  227.   { X[p] = a.xcoord();
  228.     Y[p] = a.ycoord();
  229.     p++;
  230.    }
  231.  
  232.   placement Pnew = new PLACEMENT;
  233.  
  234.  // we perform a sweep the strip consists of points q .. p-1 
  235.  
  236.  
  237.  // initialization for the sweep; the strip is empty; the first point to 
  238.  // enter is point 0; T consists of a single placement which is undefined 
  239.  // for all points 
  240.  
  241.  
  242.  p = 0; // next point to enter the strip
  243.  q = 0; // next point to leave the strip
  244.  
  245.  T.append(Pnew);        
  246.  
  247.  // The sweep: 
  248.  // we proceed as long as there is still a point to be processed and 
  249.  // the set T of legal placements is not empty 
  250.  
  251.  while (p < L.length() && !T.empty())
  252.  { 
  253.    // we decide whether p enters the strip or q leaves the strip 
  254.  
  255.    if (p == 0 || X[p]-X[q] < 2*sigma)
  256.      { 
  257.        // p enters the strip
  258.        // we combine the four possible placements of p 
  259.        // with all placements in T
  260.  
  261.        if (p-q > 16) error_handler(1,"too many points in strip");
  262.  
  263.        W.draw_filled_node(X[p],Y[p],node_color3);
  264.  
  265.        for(i=0; i<4; i++)
  266.        { 
  267.          dist_to_p = D[p][i];
  268.  
  269.          forall(v,T)
  270.          { // check whether v[q...p-1] can be extended by placement i for p 
  271.  
  272.            for(k = p-1, buf = v->get_last_word(); k >= q; k--, buf >>= 2)
  273.              if (dist_to_p[k][buf&3] < sigma) break;
  274.  
  275.            if (k < q)                
  276.            { // position i for p is compatible with placement vector v
  277.              Pnew = new PLACEMENT(*v);
  278.              Pnew->write(p,i);
  279.              Tnew.append(Pnew); 
  280.   
  281.              if (W.get_button() != 0) 
  282.              { color save = rect_color;
  283.                if (!W.mono()) rect_color = violet;
  284.                draw_config(W,L,*Pnew,sigma,p);
  285.                rect_color = save;
  286.                for(int i=q; i<=p; i++)
  287.                   W.draw_filled_node(X[i],Y[i],node_color2);
  288.                W.draw_filled_node(X[p],Y[p],node_color3);
  289.                W.read_mouse();
  290.                W.clear();
  291.                for(i=0; i<q; i++)
  292.                   W.draw_filled_node(X[i],Y[i],node_color1);
  293.                for(i=q; i<=p; i++)
  294.                   W.draw_filled_node(X[i],Y[i],node_color2);
  295.                for(i=p+1; i<n; i++)
  296.                   W.draw_filled_node(X[i],Y[i],node_color1);
  297.               }
  298.   
  299.             }
  300.  
  301.           }
  302.  
  303.         }
  304.  
  305.        W.draw_filled_node(X[p],Y[p],node_color2);
  306.  
  307.        p++;
  308.  
  309.        forall(v,T) delete v;
  310.  
  311.       } 
  312.     else 
  313.      { // q leaves the strip
  314.  
  315.        W.draw_filled_node(X[q],Y[q],node_color1);
  316.  
  317.        q++;
  318.  
  319.        // remove placement vectors identical in [q+1 ... p] from T
  320.  
  321.        plw = T.head()->get_last_word(p-q);
  322.  
  323.        Tnew.append(T.pop());
  324.  
  325.        forall(v,T)
  326.        { buf = v->get_last_word(p-q);
  327.          if (buf == plw)
  328.            delete v;
  329.          else 
  330.            { plw = buf;
  331.              Tnew.append(v);
  332.             }
  333.         }
  334.       }
  335.  
  336.     T.clear();
  337.     T.conc(Tnew); // clears Tnew
  338.  
  339.     W.draw_text(-80,-60,string("k = %2d   |T| = %5d   ",p-q+1,T.length()));
  340.  
  341.  } // end of sweep 
  342.  
  343.  while (q < p)
  344.  { W.draw_filled_node(X[q],Y[q],node_color1);
  345.    q++;
  346.   }
  347.  
  348.  
  349.  if (T.empty()) 
  350.      return false;
  351.  else 
  352.     { P = *(T.head());
  353.       forall(v,T) delete v;
  354.       return true;
  355.      }
  356.  
  357. } // end of find_placement 
  358.  
  359.  
  360.  
  361. main()
  362.   // In the first implementation we deal only with points 
  363.   // whose coordinates are integers in the range 1 .. 999;
  364.   // the algorithms consists of two steps: 
  365.   // In the first step we generate the problem and in the second step we 
  366.   // determine the optimal sigma by binary search 
  367.   // generation of the problem; we ask the user for the number of points
  368.   // then generate the appropriate number of random points 
  369.  
  370.  
  371.   W.init(-100,1100,-100);
  372.   W.set_node_width(5);
  373.   W.set_text_mode(opaque);
  374.  
  375.   if (W.mono()) 
  376.   { node_color1 = white;
  377.     node_color2 = black;
  378.    }
  379.  
  380.   int n = 50;
  381.   int input = 0;
  382.   int grid_width = 0;
  383.  
  384.   list<point> L;
  385.  
  386.   panel P;
  387.  
  388.   P.text_item("                                      ");
  389.   P.text_item("        A Plane Sweep Algorithm       ");
  390.   P.text_item("                 for a                ");
  391.   P.text_item("       Geometric Packing Problem      ");
  392.   P.text_item("                                      ");
  393.   P.text_item("                  ...                 ");
  394.   P.text_item("                  ...                 ");
  395.   P.text_item("                                      ");
  396.   P.int_item("points", n,1,80);
  397.   P.int_item("grid", grid_width, 0,40,10);
  398.  
  399.   P.button("random");
  400.   P.button("mouse");
  401.   P.button("quit");
  402.  
  403.  
  404.   for(;;)
  405.   {
  406.     int but = P.open(0,0);
  407.  
  408.     W.clear();
  409.     W.set_grid_mode(grid_width);
  410.     L.clear();
  411.  
  412.     switch(but)  {
  413.  
  414.     case 0: { init_random(n);
  415.               for(int i=0; i<n; i++) 
  416.               { double x =  random(1,999);
  417.                 double y =  random(1,999);
  418.                 L.append(point(x,y));
  419.                 W.draw_filled_node(x,y,node_color1);
  420.                }
  421.                break;
  422.              }
  423.  
  424.      case 1: { point p;
  425.                while (W >> p) 
  426.                { L.append(p);
  427.                  W.draw_filled_node(p,node_color1);
  428.                 }
  429.                break;
  430.               }
  431.  
  432.  
  433.      case 2: { exit(0);
  434.                break;
  435.               }
  436.              
  437.     }
  438.  
  439.     n = L.length();
  440.  
  441.     W.set_frame_label(string("%d points",n));
  442.  
  443.  
  444.  
  445.      // sort points  and initialize distance matrix
  446.    
  447.      L.sort();
  448.  
  449.      initialize_matrix(L);
  450.    
  451.      PLACEMENT PL;
  452.  
  453.      int low  =   1;
  454.      int high = 999;
  455.  
  456.      find_placement(L,low,PL);
  457.  
  458.      // binary search
  459.    
  460.      while (high > low+1)
  461.      { 
  462.        // Invariant:  a) PL is placement for "sigma = low"
  463.        //             b) no placement possible for "sigma = high"
  464.    
  465.        int mid = (high + low)/2;
  466.    
  467.        W.del_message();
  468.        W.message(string("%3d <= sigma < %3d      %3d ??",low, high, mid));
  469.    
  470.        if (find_placement(L,mid,PL))
  471.           { draw_config(W,L,PL,mid);
  472.             low = mid;
  473.            }
  474.         else 
  475.             high = mid;
  476.       }
  477.    
  478.      // end of the binary search 
  479.      // low is the optimal side length, PL the corresponding placement 
  480.    
  481.      W.del_message();
  482.      W.message(string("sigma = %d",low));
  483.    }
  484.                 
  485.   return 0;
  486. }
  487.